package moltencore.network.game.strategy;

import moltencore.config.Config;
import moltencore.network.game.GameLobby;
import moltencore.network.protocol.PlayerJoinedTeam;
import spark.network.protocol.Response;
import spark.network.strategy.IProtocolHandleStrategy;
import spark.network.protocol.Base;
import moltencore.network.protocol.JoinGame;
import moltencore.network.protocol.JoinGameResponse;
import moltencore.network.protocol.PlayerData;
import moltencore.network.game.exception.FullGameException;
import moltencore.game.Game;
import moltencore.game.Player;
import moltencore.player.exception.PlayerAlreadyRegisteredException;
import moltencore.player.exception.PlayerNameAlreadyExistsException;
import org.apache.log4j.Logger;
import spark.utility.OutWrapper;

import java.util.Collection;

public class JoinGameStrategy implements IProtocolHandleStrategy<JoinGame> {
	private Logger logger = Logger.getLogger(JoinGameStrategy.class);

	private Game game;
	private GameLobby lobby;

	public JoinGameStrategy(Game game, GameLobby lobby) {
		this.game = game;
		this.lobby = lobby;
	}

	@Override
	public void handle(JoinGame packet, OutWrapper<Response> acknowledgement, Collection<Base> additionalData) {
		JoinGameResponse response = new JoinGameResponse(packet);
		if(game.getState() == Game.State.Created) {
			String playerName = new String(packet.getName());
			try {
				//Player joinedPlayer = game.addPlayer(playerName, packet.getBubbleSetId(), packet.getSession(), Config.getInstance().getCannonConfiguration());
				Player joinedPlayer = lobby.addPlayer(playerName, packet.getBubbleSetId(), packet.getSession(), Config.getInstance().getCannonConfiguration());
				response.setClientId(joinedPlayer.getClientId());
				for(GameLobby.PositionedPlayer positionedPlayer : lobby.getPositionedPlayers()) {
					Player player = positionedPlayer.getPlayer();
					int playerTeamIndex = positionedPlayer.getTeamIndex();
					//add every online player to the online players except for the player who just joined
					if(packet.getSession() != player.getSession()) {
						response.getJoinedPlayers().add(new PlayerData(player));
						PlayerJoinedTeam playerJoinedTeam = new PlayerJoinedTeam(player, playerTeamIndex);
						additionalData.add(playerJoinedTeam);
					}
				}
				response.setAccepted(true);
			}
			catch(FullGameException e) {
				logger.info("Player " + playerName + " tried to log in into full game");
				response.setAccepted(false);
				response.setMessage("The game is full.");
			}
			catch(PlayerNameAlreadyExistsException e) {
				logger.info("Multiple login of player " + playerName + " attempted");
				response.setAccepted(false);
				response.setMessage("A player named " + playerName + " is already online");
			}
			catch(PlayerAlreadyRegisteredException e) {
				logger.info("Multiple login of player with session " + packet.getSession() + " attempted");
				response.setAccepted(false);
				response.setMessage("Your session " + packet.getSession() + " is already in use.");
			}
		}
		else {
			response.setAccepted(false);
			switch(game.getState()) {
				case PreparingForStart:
					response.setMessage("Game is already starting.");
					break;
				case Started:
					response.setMessage("Game has already started.");
					break;
				case Ended:
					response.setMessage("Game has already ended.");
					break;
				default:
					response.setMessage("Game is already past the joining phase.");
					break;
			}
		}
		acknowledgement.value = response;
	}
}
